package org.openkanban.client.ui.presenter;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import com.google.gwt.http.client.RequestBuilder;
import com.google.gwt.http.client.RequestBuilder.Method;
import com.google.gwt.http.client.RequestCallback;
import com.google.gwt.http.client.RequestException;
import com.smartgwt.client.util.SC;

/**
 * Powerful class that provides creation of HTTP requests by using
 * RequestParameterMaps that are created by the DTOs. Uses the GWT
 * RequestBuilder for sending the requests.
 */
public class PreparedRequest {

    private Method requestMethod = RequestBuilder.POST;

    private String[] contentHeader = { "Content-Type", "application/x-www-form-urlencoded" };

    private String servletName = "service";

    private String contextName = null;

    private String ressourceName = null;

    private Map<String, String> requestParameters = new HashMap<String, String>();

    private PreparedRequest(String contextName, String ressourceName) {
	this.contextName = contextName;
	this.ressourceName = ressourceName;
    }

    /**
     * Fills the internal parameterMap with HTTP Parameters.
     * 
     * @param contextName
     * @param ressourceName
     * @param params
     */
    public PreparedRequest(String contextName, String ressourceName, String... params) {
	this(contextName, ressourceName);

	if (params != null) {
	    for (int i = 0; i < params.length; i += 2) {
		requestParameters.put(params[i], params[i + 1]);
	    }
	}
    }

    /**
     * Fills the internal parameterMap with HTTP Parameters.
     * 
     * @param contextName
     * @param ressourceName
     * @param param
     */
    public <T extends RequestParameterMap> PreparedRequest(String contextName, String ressourceName, T param) {
	this(contextName, ressourceName);
	requestParameters.putAll(param.valuesToMap());
    }

    /**
     * Sends the prepared Request, which is configured through the constructor
     * parameters
     * 
     * @param requestCallback
     */
    public void sendAsyncRequest(RequestCallback requestCallback) {
	RequestBuilder builder = new RequestBuilder(requestMethod, servletName + "/" + contextName + "/" + ressourceName);
	builder.setHeader(contentHeader[0], contentHeader[1]);

	try {
	    String preparedRequestString = getRequestDataString();
	    builder.sendRequest(preparedRequestString, requestCallback);
	} catch (RequestException e) {
	    SC.say("Failed to send the request: " + e.getMessage());
	}
    }

    private String getRequestDataString() {
	String result = "";

	Set<String> keys = requestParameters.keySet();
	for (String key : keys) {
	    if (key != null) {
		String value = requestParameters.get(key);
		result += "&" + key + "=" + value;
	    }
	}

	return result.replaceFirst("&", "");
    }

}
